package mammuthus.tool

import com.google.inject.{Inject, Singleton}
import net.csdn.modules.transport.HttpTransportService
import net.csdn.common.reflect.ReflectHelper
import org.apache.http.client.HttpClient
import org.apache.http.client.methods.HttpGet
import java.io.{File, FileOutputStream, BufferedOutputStream, BufferedInputStream}
import net.csdn.common.logging.Loggers

/**
 * 4/28/15 WilliamZhu(allwefantasy@gmail.com)
 */
@Singleton
class FileDownloadHttpTransportService @Inject()(transport: HttpTransportService) {
  val httpClient = ReflectHelper.field(transport, "httpClient").asInstanceOf[HttpClient]
  val logger = Loggers.getLogger(getClass)

  def downloadFile(url: String, filePath: String): (Boolean, String) = {
    val dirInfo = checkDir(filePath)
    if (!dirInfo._1) {
      val msg = s"downloading $url error: ${dirInfo._2} is not exists or $filePath is exists"
      logger.info(msg)
      return (false, msg)
    }
    val httpGet = new HttpGet(url)
    val response = try httpClient.execute(httpGet) catch {
      case e: Exception =>
        val msg = s"download $url error: remote host have no response or status is not 200.${e.getMessage}"
        logger.error(msg, e)
        null
    }
    if (response == null || response.getStatusLine.getStatusCode != 200) {
      val msg = s"downloading $url error: remote host have no response or status is not 200"
      logger.info(msg)
      return (false, msg)
    }
    val entity = response.getEntity
    if (entity == null) {
      val msg = s"downloading $url error: inputStream is null"
      return (false, msg)
    }
    val bis = new BufferedInputStream(entity.getContent())
    val bos = new BufferedOutputStream(new FileOutputStream(new File(filePath)))
    try {
      var finish = true
      while (finish) {
        val inByte = bis.read()
        if (inByte == -1) finish = false
        else bos.write(inByte)
      }
    } catch {
      case e: Exception =>
        httpGet.abort()
        val msg = s"downloading $url error: downloading is interrupted by unknown reason. clean the temp file $filePath"
        val tempFile = new File(filePath)
        if (tempFile.exists()) {
          tempFile.delete()
        }
        return (false, msg)
    }
    finally {
      bis.close()
      bos.close()
    }
    return (true, "")
  }

  private def checkDir(filePath: String) = {
    val ak = filePath.split("/")
    val dir = ak.take(ak.length - 1).mkString("/")
    (new File(dir).exists() && !new File(filePath).exists(), dir)
  }
}
